#pragma once
#include "Thread.hpp"
#include "LockGuard.hpp"
#include "Task.hpp"
#include <queue>
#include <iostream>
#include <mutex>

#include <pthread.h>
using namespace std;

template<class T>
class ThreadPool;

template<class T>
struct ThreadData
{
    ThreadPool<T>* _threadpool;
    string _name;

    ThreadData(ThreadPool<T>* tp,string name):_threadpool(tp),_name(name)
    {}
};

template<class T>
class ThreadPool
{
    static const int max_num = 2;    
public:
    static ThreadPool* GetInstance(int num = max_num)
    {
        if(_pthreadpool == nullptr)
        {
            lock_guard<mutex> guard(_lock);
            if(_pthreadpool == nullptr)
            {
                _pthreadpool = new ThreadPool<T>(num);
            }
        }
        return _pthreadpool;
    }

    ~ThreadPool()
    {
        if(_pthreadpool)
        {
            cout << "~ThreadPool()" << endl;
            pthread_mutex_destroy(&_mtx);
            pthread_cond_destroy(&_cond);
            for(auto& e : _threads)
            {
                delete e;
            }
        }
    }

    // static void DelInstance()
    // {
    //     lock_guard<mutex> guard(_lock);
    //     cout << "DelInstance()" <<endl;
    //     if(_pthreadpool)
    //     {
    //         delete _pthreadpool;
    //         _pthreadpool = nullptr;
    //     }
    // }

    // class GC 
    // {
    // public:
    //     ~GC()
    //     {
    //         if(_pthreadpool)
    //         {
    //             cout << "~GC" << endl;
    //             DelInstance();
    //         }
    //     }
    // };

    void run()
    {
        for(auto& e : _threads)
        {
            ThreadData<T>* td = new ThreadData<T>(this,e->to_threadname());
            e->start(handlerTask,td);
            cout << e->to_threadname() << "start..." << endl;
        }
    }

    void push(const T& in)
    {
        LockGuard lockguard(&_mtx);
        _task_queue.push(in);
        pthread_cond_signal(&_cond);
    }

    T pop()
    {
        T t = _task_queue.front();
        _task_queue.pop();
        return t;
    }

private:
    ThreadPool(int num = max_num):_num(num)
    {
        pthread_mutex_init(&_mtx,nullptr);
        pthread_cond_init(&_cond,nullptr);
        for(int i = 0; i < _num; i++)
        {
            _threads.push_back(new Thread());
        }
    }

    static void* handlerTask(void* _args)
    {
        ThreadData<T>* td = static_cast<ThreadData<T>*>(_args);
        while(1)
        {
            T t;
            {
                LockGuard lockguard(&td->_threadpool->_mtx);
                while(td->_threadpool->_task_queue.empty())
                {
                    pthread_cond_wait(&(td->_threadpool->_cond),&(td->_threadpool->_mtx));
                }

                t = td->_threadpool->pop();
            }
            //处理任务
            std::cout << td->_name << "获取了一个任务:" << t.to_stringname() << "并处理完成，结果是:" << t() << std::endl;
        }
        delete td;
        return nullptr;
    }

private:
    int _num;   //线程个数
    vector<Thread*> _threads; //线程管理
    queue<T> _task_queue;   //任务队列
    pthread_mutex_t _mtx; //多线程互斥
    pthread_cond_t _cond; //同步

//单例模式:懒汉模式
private:
    static ThreadPool<T>* _pthreadpool;
    static mutex _lock;
    //static GC _gc;  //如果时模板类中的静态成员，如果不使用，在main结束时，是不会调用它的析构的
};

template<class T>
ThreadPool<T>* ThreadPool<T>::_pthreadpool = nullptr;
template<class T>
mutex ThreadPool<T>::_lock;
// template<class T>
// typename ThreadPool<T>::GC ThreadPool<T>::_gc;